/**
 * 
 */
package com.ms.service.module.baccarat;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ms.game.common.utility.SimpleTimer;
import com.ms.service.module.baccarat.bin.BacrBetType;
import com.xpec.c4.game.system.InitData;
import com.xpec.c4.game.utility.GUIDFactory;
import com.xpec.c4.game.utility.GameUtility;
import com.xpec.c4.game.utility.ProcessSpeedCalculator;
import com.xpec.c4.message.ConstantCode;

/**
 * 百家樂自動玩核心
 * 
 * @author TW15010
 */
public class BacrAutoPlay {
	/** log4j object */
	private static final Log log = LogFactory.getLog(BacrAutoPlay.class);

	private BacrGameCore core = new BacrGameCore();

	public static void main(String[] args) {
		InitData.initAll();
		GUIDFactory.setProcessId(1);
		GUIDFactory.setWorldId(1);

		// 要執行多少靴
		int procShoeCount = 3000000;
		if (args.length > 0 && GameUtility.isNumeric(args[0])) {
			procShoeCount = Integer.valueOf(args[0]);
		}

		// 每秒觸發一次的計時器
		SimpleTimer st = new SimpleTimer();
		st.startByRemainTime(1000);

		// 計算執行效率
		ProcessSpeedCalculator psc = new ProcessSpeedCalculator();
		psc.setEstimateTotalProcCount(procShoeCount);
		psc.start();

		BacrAutoPlay autoPlay = new BacrAutoPlay();
		BacrGameCore core = autoPlay.getCore();
		core.setSkipTimer(true);
		core.startGame(1);

		boolean haveMaxCount = (psc.getEstimateTotalProcCount() > 0);
		boolean finish = false;

		int totalHandCount = 0;

		while (true) {
			core.update();

			if (core.isHandFinish()) {
			}

			if (core.isShoeFinish()) {
				psc.increaseProcCount();
				totalHandCount += core.getHandCount();
			}

			// 數量到達，結束
			if (haveMaxCount) {
				if (core.isShoeFinish()) {
					if (core.getShoeCount() == psc.getEstimateTotalProcCount()) {
						finish = true;
					}
				}
			}

			if (st.update() || finish) {
				psc.calculateSpeed();

				if (log.isInfoEnabled()) {
					String totalCountStr;
					String remainTimeStr;
					if (haveMaxCount) {
						BigDecimal current = new BigDecimal(core.getShoeCount());
						BigDecimal total = new BigDecimal(psc.getEstimateTotalProcCount());
						BigDecimal v100 = new BigDecimal(100);
						BigDecimal rate = current.divide(total, 4, BigDecimal.ROUND_DOWN);
						rate = rate.multiply(v100);
						rate = rate.setScale(2, BigDecimal.ROUND_DOWN);

						totalCountStr = core.getShoeCount() + "/" + psc.getEstimateTotalProcCount() + " " + rate
								+ "%";

						remainTimeStr = "remainTime=" + GameUtility.remainTimeToString(psc.getRemainTime());
					} else {
						totalCountStr = core.getShoeCount() + "";

						remainTimeStr = "";
					}

					log.info("");
					log.info(totalCountStr + " speed=" + psc.getProcSpeed() + "/sec " + remainTimeStr);
				}

				st.restart();
			} // if (st.update() || finish) {

			if (finish) {
				String TAB = "\t";

				log.info("");
				log.info("==============================================================");
				log.info(TAB + "shoeCount" + TAB + core.getShoeCount() + TAB + "handCount" + TAB + totalHandCount);

				// 資料統計物件
				BacrStasticData stData = core.getStasticData();

				// 顯示勝負類型統計
				log.info(TAB + "");
				log.info(TAB + "type\tcount\trate");
				Iterator<Entry<Integer, Field>> it = ConstantCode.getIt(BacrBetType.class);
				while (it.hasNext()) {
					int type = ConstantCode.getNextValueFromIt(it);
					int count = stData.getGameResultStaticCount(type);
					BigDecimal rate = div(count, stData.getGameResultStasticTotalCount());

					if (log.isInfoEnabled()) {
						log.info(TAB + ConstantCode.getName(BacrBetType.class, type) + TAB + count + TAB + rate);
					}
				}

				// 顯示雙方手牌數量統計
				log.info(TAB + "");
				log.info(TAB + "banker card count" + TAB + "player card count" + TAB + "count" + TAB + "rate");
				for (Entry<String, Integer> entry : stData.getHandCardCountMap().entrySet()) {
					String key = entry.getKey();
					String[] vars = key.split("_");
					int count = entry.getValue();
					BigDecimal rate = div(count, stData.getHandCardStasticTotalCount());

					log.info(TAB + vars[0] + TAB + vars[1] + TAB + count + TAB + rate);
				}

				// 顯示雙方牌點組合統計
				log.info(TAB + "");
				log.info(TAB + "banker value" + TAB + "player value" + TAB + "natural" + TAB + "count" + TAB
						+ "rate");
				for (Entry<String, Integer> entry : stData.getCardValusCountMap().entrySet()) {
					String key = entry.getKey();
					String[] vars = key.split("_");
					int count = entry.getValue();
					BigDecimal rate = div(count, stData.getCardValueStasticTotalCount());

					String naturalStr = "No";
					if (vars[2].equals("1")) {
						naturalStr = "Yes";
					}

					log.info(TAB + vars[0] + TAB + vars[1] + TAB + naturalStr + TAB + count + TAB + rate);
				}

				log.info(TAB + "");
				log.info(TAB + "finish");
				log.info(TAB + "");
				break;
			}
		} // while (true) {

		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.exit(0);
	}

	public BacrGameCore getCore() {
		return core;
	}

	public void setCore(BacrGameCore core) {
		this.core = core;
	}

	public static BigDecimal div(int valueA, int valueB) {
		if (valueA == 0 || valueB == 0) {
			return BigDecimal.ZERO;
		}

		BigDecimal a = new BigDecimal(valueA);
		BigDecimal b = new BigDecimal(valueB);
		BigDecimal ans = a.divide(b, 8, BigDecimal.ROUND_DOWN);

		return ans;
	}
}
